﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;
using PwnDatSkeleton2;
using Gleed2D.InGame;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Factories;
using FarseerPhysics.Dynamics.Joints;

namespace PDS2
{
    public enum Direction
    {
        Up = 1,
        Down = 2,
        Left = 3,
        Right = 4,
    }
    public enum Control
    {
        WASD = 1,
        Keyboard = 2
    }
    public enum SpriteState
    {
        Walking,
        Attacking,
        Idle
    }

    /// <summary>
    /// Klass av Felix Östh
    /// </summary>
    public class Player
    {
        Body body;

        float rot;
        float scale = 1f;

        public Vector2 Position
        {
            get { return body.Position*64; }
            set { body.Position = value/64; }
        }

        public Body Body
        {
            get { return body; }
            set { body = value; }
        }
        public Texture2D Texture;

        Texture2D gameThumbnail;

        public Control KeyControl;
        Direction direction = Direction.Down;
        SpriteState spriteState = SpriteState.Idle;

        KeyboardState ks;
        KeyboardState lastKs;

        SaveGame save;

        int maxHp;

        public int Health = 50;
        public int Damage = 5;

        public bool isAlive = true;

        public int AttackInterval = 1;

        Map map;

        DamageDisplay dmgDisplay;

        bool immobilized = false;
        float imTimer = 0;

        public Player(Map map,ContentManager Content, SaveGame save, DamageDisplay dmg)
        {
            body = BodyFactory.CreateCircle(map.World,0.4f, 1f);
            body.UserData = this;
            body.FixedRotation = true;
            body.CollisionCategories = Category.Cat1;
            body.CollidesWith = Category.Cat3 | Category.Cat2;
            //body.AngularDamping = 2;
            body.LinearDamping = 8;
            body.BodyType = BodyType.Dynamic;


            this.dmgDisplay = dmg;
            this.map = map;
            KeyControl = Control.WASD;
            Texture = Content.Load<Texture2D>("player");
            gameThumbnail = Content.Load<Texture2D>("GameThumbnail");

            body.Position = new Vector2(10, 5);

            frameWidth = Texture.Width / 4;
            frameHeight = Texture.Height / 4;

            this.save = save;


            SetupPlayer();
            maxHp = Health;
        }

        bool sword_OnCollision(Fixture fixtureA, Fixture fixtureB, FarseerPhysics.Dynamics.Contacts.Contact contact)
        {
            if (fixtureB.Body.UserData is Enemy)
            {
                Enemy enemy = fixtureB.Body.UserData as Enemy;
                if (fixtureB.Body == enemy.Body)
                {
                    enemy.IsDamaged(Damage);
                }
            }
            return true;
        }

        private void SetupPlayer()
        {
            if (!save.ElementExist("DAMAGE"))
                save.WriteNewElement("DAMAGE=" + Damage);
            else
                Damage = int.Parse(save.GetElementValue("DAMAGE"));
            if(!save.ElementExist("HEALTH"))
                save.WriteNewElement("HEALTH=" + Health);
            else
                Health = int.Parse(save.GetElementValue("HEALTH"));
        }

        float cd;
        public void Update(GameTime gameTime, SpriteBatch spriteBatch)
        {
            spriteState = SpriteState.Idle;

            if (isAlive)
            {


                //foreach (Enemy enemy in enemies)
                //{
                //    if (enemy.Rectangle.Intersects(Rectangle))
                //    {
                //        TakeDamage(enemy.Position, enemy.Damage);
                //    }
                //}

                lastKs = ks;
                ks = Keyboard.GetState();

                //Console.WriteLine(immobilized);
                if (!immobilized)
                    Movement(spriteBatch);
                else
                {
                    imTimer += (float)gameTime.ElapsedGameTime.TotalMilliseconds;
                    if (imTimer > 400)
                    {
                        imTimer = 0;
                        immobilized = false;
                    }
                }
                Spritesheet(gameTime);

                if (Health < 1)
                {
                    isAlive = false;
                    return;
                }
            }
            else
            {
                rot += 0.1f;
                scale -= 0.01f;
                if (scale <= 0)
                {
                    map.NewPlayer(Damage, maxHp);
                }
            }
        }

        public void TakeDamage(Vector2 pos, int dmg)
        {
            immobilized = true;
            dmgDisplay.AddDisplay(dmg.ToString(), Position - new Vector2(frameWidth / 2, frameHeight/ 2 + 20), Color.Red);
            Vector2 direction = Vector2.Normalize(Position - pos);
            body.LinearVelocity = direction/64 * 1000;

            Health -= dmg;
        }

        Rectangle spriteRect;
        int currentFrame, image, frameWidth, frameHeight;
        float spriteTimer;
        /// <summary>
        /// Håller koll på allt som har med sprite sheet'et att göra
        /// </summary>
        /// <param name="gameTime"></param>
        private void Spritesheet(GameTime gameTime)
        {
            spriteRect = new Rectangle(currentFrame * frameWidth, image * frameHeight, frameWidth, frameHeight);
            if (direction == Direction.Left)
                image = 0;
            else if (direction == Direction.Right)
                image = 1;
            else if (direction == Direction.Up)
                image = 2;
            else if (direction == Direction.Down)
                image = 3;
            spriteTimer += (float)gameTime.ElapsedGameTime.TotalMilliseconds;

            switch (spriteState)
            {
                case SpriteState.Walking:
                    int interValInMs = 120;
                    if (spriteTimer > interValInMs)
                    {
                        currentFrame++;
                        spriteTimer = 0;
                    }
                    if (currentFrame == 4)
                    {
                        currentFrame = 0;
                        spriteTimer = 0;
                    }
                    break;
                case SpriteState.Idle:
                    currentFrame = 0;
                    spriteTimer = 0;
                    break;
            }
        }

        private void MeleeAttack(SpriteBatch batch)
        {
            //sword.Enabled = true;

            Rectangle rect = new Rectangle();
            switch (direction)
            {
                case Direction.Left:
                    rect = new Rectangle((int)Position.X - frameWidth / 2 - 45, (int)Position.Y - frameHeight / 2, 50, frameHeight);
                    break;
                case Direction.Right:
                    rect = new Rectangle((int)Position.X + frameWidth / 2, (int)Position.Y - frameHeight / 2, 45, frameHeight);
                    break;
                case Direction.Up:
                    rect = new Rectangle((int)Position.X - frameWidth / 2, (int)Position.Y - 70, frameWidth, 60); // lägger till lite mer
                    break;
                case Direction.Down:
                    rect = new Rectangle((int)Position.X - frameWidth / 2, (int)Position.Y + frameHeight / 2, frameWidth, 45);
                    break;
            }
            batch.Draw(gameThumbnail, rect, Color.Red);

            foreach (Enemy enemy in map.UnitMng.Enemies)
            {
                if (rect.Intersects(enemy.Rectangle))
                {
                    enemy.IsDamaged(Damage);
                }
            }
        }

        public void Draw(SpriteBatch spriteBatch, GameTime gameTime)
        {
            if (isAlive)
            {
                cd += (float)gameTime.ElapsedGameTime.TotalSeconds;
                if (cd > AttackInterval)
                {
                    if (ks.IsKeyDown(Keys.Space))
                    {
                        MeleeAttack(spriteBatch);
                        cd = 0;
                    }
                }
            }

            spriteBatch.Draw(Texture, body.Position*64, spriteRect, Color.White, rot, new Vector2(frameWidth/2, frameHeight/2), scale, SpriteEffects.None, Calc.Depth(Position));
            //spriteBatch.Draw(gameThumbnail, rect, rect, Color.White, sword.Rotation, new Vector2(0.2f, 1f) * 64, new Vector2(32f,32f)/10, SpriteEffects.None, 0.01f);
        }

        public void Movement(SpriteBatch spriteBatch)
        {
            float moveX = 0;
            float moveY = 0;
            var keyState = Keyboard.GetState();
            var MovementSpeed = 5;

            if (keyState.IsKeyDown(Keys.A))
            {
                spriteState = SpriteState.Walking;
                body.LinearVelocity = new Vector2(-MovementSpeed, body.LinearVelocity.Y);
                direction = Direction.Left;
            }
            else if (keyState.IsKeyDown(Keys.D))
            {
                spriteState = SpriteState.Walking;
                body.LinearVelocity = new Vector2(MovementSpeed, body.LinearVelocity.Y); 
                direction = Direction.Right;
            }

            if (keyState.IsKeyDown(Keys.W))
            {
                spriteState = SpriteState.Walking;
                body.LinearVelocity = new Vector2(body.LinearVelocity.X, -MovementSpeed); 
                direction = Direction.Up;
            }
            else if (keyState.IsKeyDown(Keys.S))
            {
                spriteState = SpriteState.Walking;

                body.LinearVelocity = new Vector2(body.LinearVelocity.X, MovementSpeed); 
                direction = Direction.Down;
            }

            //Console.WriteLine(new Vector2(moveX, moveY));
        }
    }
}
